package com.neuedu.base;

import com.alibaba.fastjson.JSONObject;
import com.neuedu.utils.R;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

@WebServlet(urlPatterns="/*",loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
    public static final String CONTROLLER_PACKAGE_NAME="com.neuedu.controller";

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age","3600");
        response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, token");
        response.setHeader("Access-Control-Expose-Headers","Location");

        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");


        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        uri=uri.substring(contextPath.length()+1);

        ServletInputStream inputStream = request.getInputStream();
        StringBuilder params = new StringBuilder();
        byte[] arr = new byte[1024 * 8];
        int len = 0;
        while ((len = inputStream.read(arr)) != -1) {
            params.append(new String(arr, 0, len,"UTF-8"));
        }
        if (inputStream != null) {
            inputStream.close();
        }
        if(uri.indexOf("/")<0){
            //请求错误
            response.getWriter().print(R.error("请求需要用/分隔类名和方法名"));
        }
        String[] uriString = uri.split("/");
        String className=uriString[0];
        String methodName=uriString[1];
        //反射，调用对应的类的对应的方法.
        try {
            Class<?> clazz=Class.forName(CONTROLLER_PACKAGE_NAME+"."+className);
            Method method = null;
            try {
                method = clazz.getMethod(methodName, JSONObject.class);
            } catch (NoSuchMethodException e) {
                //e.printStackTrace();
                method = clazz.getMethod(methodName, HttpServletResponse.class);
            }

            //方法不是静态的，必须要使用对象才能调用。
            Object object=clazz.newInstance();
            //执行指定的方法，拿到一个返回值
            Object result= method.invoke(object, JSONObject.parse(params.toString()));
            //把返回值转成json字符串
            String responseText = JSONObject.toJSONString(result);
            response.getWriter().print(responseText);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            //请求错误
            response.getWriter().print(R.error("DispatcherServlet反射异常"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("参数异常"));
        } catch (InstantiationException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("没有空参构造器"));
        } catch (InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("方法运行时出现错误"));
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age","3600");
        response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, token");
        response.setHeader("Access-Control-Expose-Headers","Location");
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");

        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        Map<String, String[]> parameterMap = request.getParameterMap();
//        for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {
//            System.out.println(stringEntry.getKey());
//            System.out.println(stringEntry.getValue());
//        }
        if(parameterMap==null){
            parameterMap=new HashMap<>();
        }

        /**
         *    /mvc/TestController/hello
         *    /mvc
         */
        uri=uri.substring(contextPath.length()+1);
        if(uri.indexOf("/")<0){
            //请求错误
            response.getWriter().print(R.error("请求需要用/分隔类名和方法名"));
        }
        String[] uriString = uri.split("/");
        String className=uriString[0];
        String methodName=uriString[1];
        //反射，调用对应的类的对应的方法.
        try {
            Class<?> clazz=Class.forName(CONTROLLER_PACKAGE_NAME+"."+className);
            Method method = null;
            boolean flag=true;
            try {
                method = clazz.getMethod(methodName, Map.class);
            } catch (NoSuchMethodException e) {
//                e.printStackTrace();
                flag=false;
                method = clazz.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
            }
            //方法不是静态的，必须要使用对象才能调用。
            Object object=clazz.newInstance();
            //执行指定的方法，拿到一个返回值
            if(flag) {
                Object result = method.invoke(object, parameterMap);
                //把返回值转成json字符串
                String responseText = JSONObject.toJSONString(result);
                response.getWriter().print(responseText);
            }else{
                method.invoke(object,request,response);
            }
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
            //请求错误
            response.getWriter().print(R.error("DispatcherServlet反射异常"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("参数异常"));
        } catch (InstantiationException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("没有空参构造器"));
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            response.getWriter().print(R.error("方法运行时出现错误"));
        }
    }
}
